home *** CD-ROM | disk | FTP | other *** search
/ PsL Monthly 1993 December / PSL Monthly Shareware CD-ROM (December 1993).iso / prgmming / dos / c / fileshr.exe / FILESHAR.C < prev    next >
C/C++ Source or Header  |  1993-01-10  |  11KB  |  286 lines

  1. /* THIS PROGRAM IS INTENDED TO HELP THOSE POOR PEOPLE WHO ARE TRYING TO
  2.    LEARN HOW TO IMPLEMENT FILE SHARING ON A LAN.
  3.  
  4.    I had a tough time figuring out which functions where intended for
  5.    file sharing on a LAN and which ones only worked for process locking.
  6.    I have both a Novell network and a LANtastic network to play on.
  7.  
  8.    The following simple program demonstrates how I will implement file
  9.    sharing in my future programs.
  10.  
  11.    File locking can be done in 2 ways:
  12. 1) For buffered I/O (streams), you can only do file locking.  (You lock the
  13.    entire file).  This is done by opening the file in (O_RDONLY | SH_DENYNONE)
  14.    mode if you wish to share the data, or (O_RDWRITE | SH_DENYALL) if you
  15.    are updating the data.  Your program simple checks to see if IT can
  16.    lock the file.  It should be fairly obvious that data cannot be
  17.    written AND shared if it is buffered at the workstation.  Example of
  18.    this type of function is:  _fsopen() or fopen().
  19.  
  20. 2) With unbuffered I/O (handles), you can also do region locking.  This is
  21.    the way to go.  This function requires that SHARE.EXE be loaded at the
  22.    DOS server.  (Note: NOVELL servers provide all the required functionality)
  23.    By using lock() to control access to various regions of the file, you
  24.    can have multiple users reading concurrently, while users can be updating
  25.    data.  There are two restrictions.  You should buffer the users input
  26.    to minimize the time that a region is locked, and you should be very
  27.    carefull about deadlocking.  deadlocking is when two programs are waiting
  28.    for each other, with no way out.
  29.    Deadlocking is handled very nicely with locking(), however it is
  30.    assumed that you will not be locking the region for more than 10 secs.
  31.  
  32.    Unbuffered file I/O allows you to use the disk as a real time virtual
  33.    array. I would normally use binary I/O with structures for database data.
  34.  
  35. Here is how its done.  The process is fairly simple:
  36.       offset = record_num * sizeof(struct)
  37.       len = sizeof(struct)
  38.       buffer =  &(struct[record_num])
  39.  
  40. 1) For READING data:
  41.    handle = sopen( file, O_RDONLY, O_DENYNONE | O_BINARY, S_IREAD);
  42.    lseek(handle, offset, SEEK_SET);
  43.    if( bytes = read(handle, buffer, len) == 0) {
  44.        printf("error reading data"); }
  45.    close(handle);
  46.  
  47. 1) or sequencially READING data:
  48.    handle = sopen( file, O_RDONLY, O_DENYNONE | O_BINARY, S_IREAD);
  49.    lseek(handle, 0L, SEEK_SET);
  50.    while (NOT EOF) {
  51.      if( bytes = read(handle, buffer, len) == 0) {
  52.        printf("error reading data");
  53.        lseek(handle, len, SEEK_CUR); }
  54.    }
  55.    close(handle);
  56.  
  57. 2) For READING/WRITING data:
  58.    handle = sopen( file, O_RDWR, O_DENYNONE | O_BINARY, S_IREAD | S_IWRITE);
  59.    lseek(handle, offset, SEEK_SET); or lseek(handle, len, SEEK_CUR);
  60.    if (stat = lock(handle, offset, len) == 0) {
  61.      write(handle, buffer, len);
  62.      unlock(handle, offset, len);
  63.    } else { printf("Unable to access, %s", sys_errlist[errno]) }
  64.    close(handle);
  65.  
  66. /* This sample file shows file locking on a LAN. It also works for multiple
  67.    processes on a PC (eg DOSSHELL and windows). It implements the following:
  68.    - if data file "TEST0000.$$$" does not exist, creates it.
  69.    - if data file cannot be modified, abort.
  70.    - Loop, - opening file in RDONLY mode,
  71.            - sequentially read each record, if record cannot be read,
  72.                skip it with a message.
  73.            - close file.
  74.            - check for keyboard hit.
  75.    - On kbhit:
  76.            - Ask for record number to edit.
  77.            - open file in shared RDWR mode.
  78.            - lock region for this record.
  79.            - input from user.
  80.            - writes data to file.
  81.            - unlocks region.
  82.            - close file.
  83.  
  84. /* NOTE:  This programs runs as BOTH the locking process and as a reading
  85.           process. Eg. on a LAN, run this on two (or more) machines, */
  86.  
  87. #include <stdio.h>
  88. #include <fcntl.h>
  89. #include <sys\stat.h>
  90. #include <share.h>
  91. #include <io.h>
  92. #include <conio.h>
  93. #include <string.h>
  94. #include <errno.h>
  95. #include <stdlib.h>
  96.  
  97. #define MAXARRAY 15
  98. #define ESC      27
  99. #define OR       ||
  100. #define AND      &&
  101.  
  102. struct data_st {        /* I'm using a sample struct for disk IO*/
  103.        char string[62]; /* Normally, I would consider the disk file */
  104.        int number;      /* a virtual array, with direct binary IO. */
  105.        } data[MAXARRAY];/* Also, when sharing, all data is unbuffered */
  106.  
  107. /*-----------------------------------------------------------------
  108.   main()
  109.   -----------------------------------------------------------------*/
  110. void main( void) {
  111.      void InitFile(char *file);  /*Progamming Hint: always use prototype */
  112.      void ReadFile( char *file); /*in function which uses it :) */
  113.      void EnterRecord(char *file);
  114.  
  115.      int  handle;
  116.      int  count;
  117.      int  ch;
  118.      char file[] = "test0000.$$$"; /* sample data file name*/
  119.  
  120.      clrscr();
  121. cprintf("This program demonstrates how to implement file sharing using TC 3.0.\n\r");
  122. cprintf("Run this program an several PC's on a lan, or several process on a PC,\n\r");
  123. cprintf("then edit a record on one or more systems.  This is intended as an education\n\r");
  124. cprintf("tool using sopen(), lseek(), lock(), and unlock(). Requires SHARE be loaded.\n\r");
  125.      gotoxy(1,25);
  126.      cprintf("Hit ESC to exit program, Any other key to enter data");
  127.      /* test to see if file exists */
  128.      if ( access(file,0) != 0) {
  129.         InitFile( file);
  130.      }
  131.  
  132.      /* test to see if file is locked by R attribute :( */
  133.      if ( access(file,6) != 0) {
  134.         cprintf("Attrib on %s says it cannot be MODIFIED\n\r", strupr(file));
  135.         exit(-1);
  136.         /*Note: There seems to be a flaw in access().  See the TC 3.0 Help
  137.         example for sample sopen().  The flaw in access() is that it should
  138.         show file locks from other workstations, but it only shows DOS not
  139.         allowing writes, which can only happen from an R attribute */
  140.      }
  141.  
  142. /*- Main Program-*/
  143.      ch = 0; /* clear input from keyboard */
  144.      do {
  145.         ReadFile(file);
  146.         if (kbhit()) { /* Loop until a key is hit */
  147.            if ( (ch = getch()) != ESC) {
  148.               EnterRecord( file);
  149.               ch = 0;
  150.            }
  151.         }
  152.      } while (ch != ESC);
  153. }
  154.  
  155. /*-----------------------------------------------------------------
  156.   InitFile()
  157.   -----------------------------------------------------------------*/
  158. void InitFile(char *file)
  159. {
  160.    int count;
  161.    int handle;
  162.    char junk[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  163.  
  164.    /* Fill array with unique junk */
  165.    for (count = 0; count < MAXARRAY; count++) {
  166.        strcpy(data[count].string, &junk[count]);
  167.        data[count].number = 11 * count;
  168.    }
  169.  
  170.    /* Open read/write, full lock*/
  171.    handle = sopen( file, O_RDWR | O_CREAT | O_TRUNC,
  172.                          O_DENYALL | O_BINARY,
  173.                          S_IREAD|S_IWRITE);
  174.    if (handle < 1)  {
  175.       printf("sopen failed\n");
  176.       exit(-1);
  177.    } else {
  178.    /* Note: Write whole file in one burst*/
  179.      count = write(handle, data, sizeof(data));
  180. /*   printf("Data file created by sopen(), %d bytes written\n", count);*/
  181.      close(handle);
  182.    }
  183. }
  184.  
  185. /*-----------------------------------------------------------------
  186.   ReadFile()
  187.   -----------------------------------------------------------------*/
  188. void ReadFile( char *file)
  189. {
  190.    int handle;
  191.    int bytes;
  192.    int count;
  193.  
  194.    /*- Read data into memory -*/
  195.    handle = sopen( file, O_RDWR,
  196.                          O_DENYNONE | O_BINARY,
  197.                          S_IREAD | S_IWRITE);
  198.  
  199.    if (handle < 1)  {
  200.       printf("sopen failed\n");
  201.       exit(-1);
  202.    } else {
  203.      /*-Sequentially read all records-*/
  204.      lseek(handle, 0l, SEEK_SET);
  205.      for (count = 0; count < MAXARRAY; count++) {
  206.          /*Note: read file one record at a time (virtual array)*/
  207.          bytes = read(handle, &data[count], sizeof(data[count]));
  208.          gotoxy(1, count +5);
  209.          if (bytes > 0) {
  210.             /* printdata */
  211.             cprintf("Record %2d ", count);
  212.             cprintf(" >%s %d<